﻿using System;

namespace Algoritmia.Utils
{
    public class RandomGaussian : IRandomProvider
    {
        private double? _cache;
        private readonly Random _random;

        public RandomGaussian()
        {
            _cache = null;
            _random = new Random();
        }

        #region IRandomProvider implementation

        public double NextDouble()
        {
            if (_cache != null)
            {
                double v = _cache.Value;
                _cache = null;
                return v;
            }

            double rsq, v1, v2;
            do
            {
                v1 = (2.0 * _random.NextDouble()) - 1.0;
                v2 = (2.0 * _random.NextDouble()) - 1.0;
                rsq = (v1 * v1) + (v2 * v2);
            }
            while (rsq > 1.0 || rsq == 0);

            double fac = Math.Sqrt(-2.0 * Math.Log(rsq) / rsq);
            _cache = v1 * fac;
            return v2*fac;
        }

        public double NextGaussian(double mean, double sigma)
        {
            return sigma*NextDouble() + mean;
        }

        #endregion
    }
}
